"""
1. 你需要实现一个功能，用于接口批量提交 10 万条地理位置数据到服务端，并确保提交的数据满足以下条件：
 (1) 数据格式
data = {
 "name": "kfc",
 "latitude": -6.177648650,
 "longitude": 106.8212953,
 "type": "restaurant" # 可选字段
}
(2) 数据生成
① name 从预定义列表选取符合下面格式要求的数据（如["kfc", "mcd",
"starbucks", ...]
1) name 只能包含字符和空格
2) name 长度小于 10
② 坐标在合理范围内随机生成（如纬度[-90, 90]，经度[-180, 180]）,
保留 6 位小数
③ name 可以重复, 坐标不能重复
④ type 从列表中选择['restaurant', 'shop', 'mall']
(3) 数据提交
模拟 HTTP 请求将数据提交到服务端（用 requests.post 模拟）, 提交成
功状态码 200
(4) 测试报告,包含以下指标
① 成功提交量、失败提交量、失败提交数据
② 统计不同 type 数据量（如返回{"restaurant": 500, "shop": 300}）
"""
import json
import random
import time
from concurrent.futures import ThreadPoolExecutor, as_completed

import requests
from requests.adapters import HTTPAdapter
from urllib3 import Retry

name_list = ["kfc", "mcd", "starbucks", "xbk"]
types = ['restaurant', 'shop', 'mall']
last_data = [

]

url = "http://100.74.27.72:5001/submit_geography"
batch_size = 50
concurrent_works = 10
max_retry = 3
time_out = 15


def generate_unique_coordinates(count):
    """生成指定数量的 坐标"""
    unique_coords = []
    seen = set()
    while len(unique_coords) < count:

        latitude = round(random.uniform(-90, 90), 6)
        longitude = round(random.uniform(-90, 90), 6)
        coord_tuple = (latitude, longitude)
        if coord_tuple not in seen:
            seen.add(coord_tuple)
            unique_coords.append({
                "name": random.choice(name_list),
                "latitude": latitude,
                "longitude": longitude,
                "type": random.choice(types)
            })

    return unique_coords


def create_session():
    session = requests.Session()
    retry_stratrgy = Retry(
        total=max_retry,
        backoff_factor=1,
        status_forcelist=[429, 500, 502, 503, 504]
    )
    adapter = HTTPAdapter(
        max_retries=retry_stratrgy,
        pool_connections=100,
        pool_maxsize=100
    )
    session.mount("http://", adapter)
    session.mount("https://", adapter)
    return session


def send_dict_request(seesion, data_dict, request_id):
    """发送单个字典数据的请求"""
    try:
        response = seesion.post(
            url,
            headers={"Content-Type": "application/json"},
            data=json.dumps(data_dict),
            timeout=time_out
        )
        response.raise_for_status()
        return {
            "success": True,
            "request_id": request_id,
            "response": response.json(),
            "status_code": response.status_code
        }
    except requests.exceptions as e:
        return {
            "success": False,
            "request_id": request_id,
            "response": str(e),
            "data": data_dict
        }


def process_batch(session, batch, batch_num):
    """"""
    results = []
    with ThreadPoolExecutor(max_workers=concurrent_works) as exe:
        futures = {
            exe.submit(send_dict_request, session, data_dict, f"{batch_num}_{i}"): (data_dict, i) for i, data_dict in
            enumerate(batch)
        }
        for future in as_completed(futures):
            results.append(future.result())
    return results


def main(all_dicts):
    start_time = time.time()
    session = create_session()
    total = len(all_dicts)
    all_result = []
    fail = []
    print(f"------------开始处理{total}个数据....")

    for batch_num in range(0, total, batch_size):
        batch_start = batch_num
        batch_end = min(batch_num + batch_size, total)
        current_batch = all_dicts[batch_start:batch_end]

        batch_results = process_batch(
            session,
            current_batch,
            batch_num
        )
        all_result.extend(batch_results)
        batch_failed = [r for r in batch_results if not r["success"]]
        if batch_failed:
            print(f"失败提交量:{batch_failed}个请求")
        if (batch_num // batch_size + 1) % 5 == 0:
            time.sleep(1)
        if fail:
            print(f"重试{len(batch_failed)}个失败的的请求")
        print("处理完成")


if __name__ == '__main__':
    # 需要请求的内容
    req_items = generate_unique_coordinates(10000000)
    main(req_items)
